import java.io.*;
import java.util.*;

public class YahtzeeGame {
	

	public static Random rand;
	private LinkedList<Player> _players = new LinkedList<Player>();
	private GameState _gameState;
	private boolean _shouldRun = true;

	YahtzeeGame() {}

	public String run(int numGames, boolean verbose) {
		int total = 0;
		System.out.println("Starting " + numGames + " games");
		String rez = "";
		for (int i=0; i<numGames; i++) {
			_gameState = new GameState(_players.size());
			while(_shouldRun) {
				_shouldRun = false;
				for (Player p : _players) {
					p.takeTurn(_gameState);
					_shouldRun = _shouldRun || !p.finished();
				}
			}
			if (verbose) System.out.println("Final Scoring\n-------------");
			for (Player p : _players) {
				int score = _gameState.getScore(p.getIndx());
				total += score;
				if(verbose) System.out.println(p.getName() + " " + score);
				if(verbose) rez += score + " ";
				p.reset();
			}
			_shouldRun = true;
			rez = rez.trim();
			rez += "\n";
		}
		rez += "Mean: " + (1.0 * total / numGames);

		for (Player p : _players) {
			System.out.println(p.getName() + " " + _gameState.getScore(p.getIndx()));			
			p.shutDown();
		}
		return rez;
	}

	public void addPlayer(String name, String addr, int port, int totalPlayers) {
		_players.add(new Player(name, addr, port, _players.size(),totalPlayers));
	}

	public void addPlayer(String name, String addr, int port, int totalPlayers, boolean verbose) {
		_players.add(new Player(name, addr, port, _players.size(), totalPlayers, verbose));
	}


	public static void pressEnterToContinue() {
		System.out.println("Press ENTER to continue...");
		try {
			System.in.read();
			while (System.in.available() > 0)
				System.in.read(); //flush the buffer
		} catch (IOException e) {
				e.printStackTrace();
		}
	}


	public static void main(String [] args) {
	
		int nPlayers = 1;
		int numGames = 1;
		boolean verbose = false;
		if (args.length > 0) nPlayers = Integer.valueOf(args[0]);

		if (args.length > 1) {
			numGames = Integer.valueOf(args[1]);
		}

		if (args.length > 2) {
			verbose = args[2].equalsIgnoreCase("true");
		}

		YahtzeeGame g = new YahtzeeGame();
		YahtzeeGame.rand = new Random();


		for (int i=0; i<nPlayers; i++) {
			if (verbose) {
				g.addPlayer("player" + i, "127.0.0.1",i+7000, nPlayers, true);
			} else {
				g.addPlayer("player" + i, "127.0.0.1",i+7000, nPlayers);
			}
		}
		String rez = g.run(numGames, verbose);
		System.out.println("Batch Results\n-------------\n" + rez);
		

		/*if (args.length > 1) {
			pressEnterToContinue();
		}*/
		
		//testHands();
	}

	public static void testHands() {
		Player nate = new Player("nate", "derf", 69, 0, 0);
		DiceRoll dr = new DiceRoll();
		GameState gs = new GameState(1);
		//test ones
		dr._dice[0] = 1;
		dr._dice[1] = 1;
		dr._dice[4] = 1;
		testRoll(true,nate,dr,gs,GameState.ONES);
		//test fours
		dr._dice[0] = 4;
		dr._dice[1] = 4;
		dr._dice[4] = 4;
		testRoll(true,nate,dr,gs,GameState.FOURS);
		//test 3K
		dr._dice[0] = 6;
		dr._dice[1] = 6;
		dr._dice[4] = 6;
		testRoll(true,nate,dr,gs,GameState.THREE_OF_A_KIND);
		dr._dice[2] = 5;
		dr._dice[3] = 3;
		dr._dice[4] = 1;
		testRoll(true,nate,dr,gs,GameState.THREE_OF_A_KIND);
		//test 4K
		dr._dice[0] = 6;
		dr._dice[3] = 6;
		dr._dice[1] = 6;
		dr._dice[4] = 6;
		testRoll(true,nate,dr,gs,GameState.FOUR_OF_A_KIND);
		dr._dice[1] = 3;
		dr._dice[4] = 3;
		testRoll(true,nate,dr,gs,GameState.FOUR_OF_A_KIND);
		//test FH
		dr._dice[0] = 6;
		dr._dice[1] = 6;
		dr._dice[2] = 6;
		dr._dice[3] = 3;
		dr._dice[4] = 3;
		testRoll(true,nate,dr,gs,GameState.FULL_HOUSE);
		dr._dice[1] = 5;
		dr._dice[4] = 2;
		testRoll(true,nate,dr,gs,GameState.FULL_HOUSE);
		//test SS
		dr._dice[0] = 5;
		dr._dice[1] = 2;
		dr._dice[2] = 3;
		dr._dice[3] = 4;
		testRoll(true,nate,dr,gs,GameState.SMALL_STRAIGHT);
		dr._dice[3] = 5;
		dr._dice[4] = 5;
		testRoll(true,nate,dr,gs,GameState.SMALL_STRAIGHT);
		//test LS
		dr._dice[0] = 1;
		dr._dice[1] = 2;
		dr._dice[2] = 3;
		dr._dice[3] = 4;
		dr._dice[4] = 5;
		testRoll(true,nate,dr,gs,GameState.LARGE_STRAIGHT);
		dr._dice[4] = 6;
		testRoll(true,nate,dr,gs,GameState.LARGE_STRAIGHT);
		//test Y / Cnance
		dr._dice[0] = 1;
		dr._dice[1] = 1;
		dr._dice[2] = 1;
		dr._dice[3] = 1;
		dr._dice[4] = 1;
		testRoll(true,nate,dr,gs,GameState.YAHTZEE);
		dr._dice[4] = 2;
		testRoll(true,nate,dr,gs,GameState.YAHTZEE);
		testRoll(true,nate,dr,gs,GameState.CHANCE);
	}

	public static void testRoll(boolean overide, Player p, DiceRoll dr, GameState gs, int cat) {
		System.out.println("Testing " + GameState.hr(cat));
		System.out.println(dr);
		p.scoreRoll(gs,dr,cat,overide);
		System.out.println();
	}

}
